package org.stvd.common.security.support;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.stvd.common.Consts;
import org.stvd.entities.admin.Resources;
import org.stvd.entities.admin.Roles;
import org.stvd.service.admin.ResourcesService;
import org.stvd.service.admin.RolesService;

//1 加载资源与权限的对应关系
public class UrlSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    private Logger logger = LoggerFactory.getLogger(getClass());
    
    private static Map<String, Collection<ConfigAttribute>> resourceMap = null;

    public static void setResourceMap(Map<String, Collection<ConfigAttribute>> resourcemap) {
        if (resourceMap == null) {
            resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
        } else {
            resourceMap.clear();
        }
        resourceMap.putAll(resourcemap);
    }

    private final PathMatcher pathMatcher = new AntPathMatcher();
    // private PasswordEncoder passwordEncoder = new Md5PasswordEncoder();
    private ResourcesService resourcesService;
    
    private RolesService rolesService;

    public ResourcesService getResourcesService() {
        return resourcesService;
    }

    public void setResourcesService(ResourcesService resourcesService) {
        this.resourcesService = resourcesService;
    }
    
    public RolesService getRolesService() {
        return rolesService;
    }

    public void setRolesService(RolesService rolesService) {
        this.rolesService = rolesService;
    }

    // 由spring调用
    public UrlSecurityMetadataSource(ResourcesService resourcesService, RolesService rolesService) {
        this.resourcesService = resourcesService;
        this.rolesService = rolesService;
        loadResourceDefine();
    }

    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    public boolean supports(Class<?> clazz) {
        return true;
    }

    // 加载所有资源与权限的关系,得到所有资源以及每个资源对应的角色
    private void loadResourceDefine() {
        if (resourceMap == null) {
            resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
        } else {
            resourceMap.clear();
        }

        Collection<ConfigAttribute> configConsts = new ArrayList<ConfigAttribute>();

        // 以权限名封装为Spring的security Object,例如ROLE_USER,ROLE_ADMIN
        /*
         * 系统默认的角色资源：ROLE_ANONYMOUS（/login）
         */
        ConfigAttribute configConst = new SecurityConfig("ROLE_ANONYMOUS");
        configConsts.add(configConst);
        resourceMap.put("/login**", configConsts);
        resourceMap.put("/sign**", configConsts);
        //系统有效期校验，SysAuthentication设置后系统到期后用户登陆无权限
//        SysAuthentication sysAuthentication = new SysAuthentication();
//        if (!sysAuthentication.verify()) {
//            return;
//        }

        logger.info("    Request GUID:"+Consts.GUID);
        List<Resources> resources = this.resourcesService.findResourcesByType("URL", Consts.GUID);
        for (Resources resource : resources) {
            Collection<ConfigAttribute> configAttributes = new ArrayList<ConfigAttribute>();
            // 以权限名封装为Spring的security Object,例如ROLE_USER,ROLE_ADMIN
            List<Roles> roleList = rolesService.getRolesByResId(resource.getResId());
            for (Roles role : roleList) {
                ConfigAttribute configAttribute = new SecurityConfig(role.getRoleCode());
                configAttributes.add(configAttribute);
            }
            resourceMap.put(resource.getContent(), configAttributes);
        }
    }

    // 返回所请求资源所需要的权限
    // 将请求url和资源库比较，符合则将资源库的角色定义赋值给当前请求url
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        if ((object == null) || !this.supports(object.getClass())) {
            // logger.info("Object must be a FilterInvocation");
            throw new IllegalArgumentException("Object must be a FilterInvocation");
        }
        Collection<ConfigAttribute> configAttributes = new ArrayList<ConfigAttribute>();

        if (object instanceof FilterInvocation) {
            String requestUrl = ((FilterInvocation) object).getRequestUrl();
            String requestMethod = ((FilterInvocation) object).getHttpRequest().getMethod();
            
            logger.info("    Request url:["+requestMethod+"]"+requestUrl);
            
            // 比较请求url和资源库url，匹配则赋予对应的角色权限
            if (resourceMap != null && !resourceMap.isEmpty()) {
                Iterator<String> iterator = resourceMap.keySet().iterator();
                while (iterator.hasNext()) {
                    String resourceUrl = iterator.next();
                    if (pathMatcher.match(resourceUrl, requestUrl)) {
                        configAttributes.addAll(resourceMap.get(resourceUrl));
                    }
                }
                if (configAttributes.isEmpty()) {
                    configAttributes.add(new SecurityConfig("nobody"));
                }
                
                logger.info("    Request url need roles:"+configAttributes);
//                for (ConfigAttribute configAttribute : configAttributes) {
//                    System.out.println(configAttribute.toString());
//                }
                return configAttributes;
            }
        }
        return null;
    }
}
